#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>

/* 波特率设定被定义在 <asm/termbits.h>, 这在 <termios.h> 被引入 */
#define BAUDRATE B38400
/* 定义正确的序列埠 */
#define MODEMDEVICE "/dev/ttyUSB0"
#define _POSIX_SOURCE 1 /* POSIX 系统兼容 */

#define FALSE 0
#define TRUE 1

volatile int STOP=FALSE;

main()
{
  int fd,c, res;
  struct termios oldtio,newtio;
  char buf[255];
/* 
  开启数据机装置以读取并写入而不以控制 tty 的模式
  因为我们不想程序在送出 CTRL-C 后就被杀掉.
*/
  fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
  if(fd <0) 
  {
      perror(MODEMDEVICE); 
      exit(-1);
  }

  tcgetattr(fd,&oldtio); /* 储存目前的序列埠设定 */
  bzero(&newtio, sizeof(newtio)); /* 清除结构体以放入新的序列埠设定值 */

/* 
  BAUDRATE: 设定 bps 的速度. 你也可以用 cfsetispeed 及 cfsetospeed 来设定.
  CRTSCTS : 输出资料的硬件流量控制 (只能在具完整线路的缆线下工作
            参考 Serial-HOWTO 第七节)
  CS8     : 8n1 (8 位元, 不做同位元检查,1 个终止位元)
  CLOCAL  : 本地连线, 不具数据机控制功能
  CREAD   : 致能接收字元
*/
  newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
  //newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
  newtio.c_iflag = IGNPAR;
  newtio.c_oflag = 0;

/* 设定输入模式 (非标准型, 不回应,...) */
  newtio.c_lflag = 0;
  newtio.c_lflag = ~ICANON;

  newtio.c_cc[VTIME]    = 0;   /* 不使用分割字元组计时器 */
  newtio.c_cc[VMIN]     = 3;   /* 在读取到 5 个字元前先停止 */

/* 现在清除数据机线并启动序列埠的设定*/
 tcflush(fd, TCIFLUSH);
 tcsetattr(fd,TCSANOW,&newtio);

/*终端机设定完成, 现在处理输入信号在这个范例, 在一行的开始处输入 'z' 会退出此程序.*/
 while (STOP==FALSE) 
 {  /* 输入回圈 */                        
    res = read(fd,buf,255); /* 在输入 5 个字元后即返回 */
    buf[res]=0;             /* 设定字串终止字元, 所以我们能用 printf */
    printf(":%s:%d\n", buf, res);
    if (buf[0]=='z') STOP=TRUE;
 }
 /* 回存旧的序列埠设定值 */
 tcsetattr(fd,TCSANOW,&oldtio);
}
